package main

import (
	"database/sql" // 导入 database/sql 包，用于数据库操作
	"log"          // 导入 log 包，用于日志输出
	"net/http"     // 导入 net/http 包，用于 HTTP 操作

	"github.com/gin-contrib/cors"      // 导入 gin-contrib/cors 包，用于设置跨域资源共享(CORS)规则
	"github.com/gin-gonic/gin"         // 导入 gin-gonic/gin 包，用于构建 Web 应用程序
	_ "github.com/go-sql-driver/mysql" // 导入 mysql 驱动包，用于连接 MySQL 数据库
)

// Course 结构体用于表示课程信息
type Course struct {
	ID             int    `json:"id" db:"id"`                           // ID 表示课程的唯一标识，对应数据库中的 id 字段
	CourseName     string `json:"course_name" db:"course_name"`         // CourseName 表示课程名称，对应数据库中的 course_name 字段
	CourseTime     string `json:"course_time" db:"course_time"`         // CourseTime 表示课程时间，对应数据库中的 course_time 字段
	CourseLocation string `json:"course_location" db:"course_location"` // CourseLocation 表示课程地点，对应数据库中的 course_location 字段
}

//这段代码是用来设置路由的功能。首先初始化了一个gin引擎，并启用了默认的中间件。然后使用了cors.Default()来处理跨域请求。接着加载了HTML模板文件夹中的所有模板文件。
//下面分别定义了几个路由：//
//GET请求 /kc，调用getAllCourses函数来获取所有课程信息。
//GET请求 /kzz，调用getAllCoursesJSON函数来获取所有课程信息并以JSON格式返回。
//POST请求 /createCourse，调用createCourse函数来创建一个新的课程。
//PUT请求 /updateCourse/:id，调用updateCourse函数来更新指定id的课程信息。
//DELETE请求 /deleteCourse/:id，调用deleteCourse函数来删除指定id的课程。
//OPTIONS请求 /courses，处理OPTIONS请求的函数。
//GET请求 /create_course，展示创建课程的表单页面。
//GET请求 /update_course.html，展示更新课程的表单页面。
//最后返回了设置好路由的gin引擎。整个代码的作用是为不同的请求设置了相应的处理函数，用于处理课程信息的获取、创建、更新和删除操作，并提供了展示表单页面的功能。//

func setupRoutes(db *sql.DB) *gin.Engine {
	r := gin.Default()
	r.Use(cors.Default())

	r.LoadHTMLGlob("templates/*")

	r.GET("/kc", func(c *gin.Context) {
		getAllCourses(c, db)
	})

	r.GET("/kzz", func(c *gin.Context) {
		getAllCoursesJSON(c, db)
	})

	r.POST("/createCourse", func(c *gin.Context) {
		createCourse(c, db)
	})

	r.PUT("/updateCourse/:id", func(c *gin.Context) {
		updateCourse(c, db)
	})

	r.DELETE("/deleteCourse/:id", func(c *gin.Context) {
		deleteCourse(c, db)
	})

	r.OPTIONS("/courses", func(c *gin.Context) {
		handleOptionsRequest(c)
	})

	r.GET("/create_course", func(c *gin.Context) {
		showCreateCourseForm(c)
	})

	r.GET("/update_course.html", func(c *gin.Context) {
		showUpdateCourseForm(c)
	})

	return r
}

func getAllCourses(c *gin.Context, db *sql.DB) {
	rows, err := db.Query("SELECT id, course_name, course_time, course_location FROM courses")
	if err != nil {
		c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
		return
	}
	defer rows.Close()

	var courseSlice []Course

	for rows.Next() {
		var course Course
		if err := rows.Scan(&course.ID, &course.CourseName, &course.CourseTime, &course.CourseLocation); err != nil {
			log.Println("Error scanning row:", err)
			continue
		}
		courseSlice = append(courseSlice, course)
	}

	if err := rows.Err(); err != nil {
		log.Println("Error after rows.Next() loop:", err)
		c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
		return
	}

	// 返回JSON格式的课程列表
	c.HTML(http.StatusOK, "kc.html", gin.H{
		"student_slice": courseSlice,
	})

}

func getAllCoursesJSON(c *gin.Context, db *sql.DB) {
	rows, err := db.Query("SELECT id, course_name, course_time, course_location FROM courses")
	if err != nil {
		c.JSON(http.StatusInternalServerError, gin.H{"error": "Failed to query courses: " + err.Error()})
		return
	}
	defer rows.Close()

	var courses []Course
	for rows.Next() {
		var course Course
		if err := rows.Scan(&course.ID, &course.CourseName, &course.CourseTime, &course.CourseLocation); err != nil {
			log.Println("Error scanning row:", err)
			continue
		}
		courses = append(courses, course)
	}

	if err := rows.Err(); err != nil {
		c.JSON(http.StatusInternalServerError, gin.H{"error": "Error after rows.Next() loop: " + err.Error()})
		return
	}

	c.JSON(http.StatusOK, courses)
}

func createCourse(c *gin.Context, db *sql.DB) {
	var newCourse Course
	if err := c.BindJSON(&newCourse); err != nil {
		c.JSON(http.StatusBadRequest, gin.H{"error": "Invalid JSON data: " + err.Error()})
		return
	}

	_, err := db.Exec("INSERT INTO courses (course_name, course_time, course_location) VALUES (?, ?, ?)",
		newCourse.CourseName, newCourse.CourseTime, newCourse.CourseLocation)
	if err != nil {
		c.JSON(http.StatusInternalServerError, gin.H{"error": "Failed to create course: " + err.Error()})
		return
	}

	c.JSON(http.StatusOK, gin.H{"message": "课程创建成功"})
}

func updateCourse(c *gin.Context, db *sql.DB) {
	var updatedCourse Course
	if err := c.BindJSON(&updatedCourse); err != nil {
		c.JSON(http.StatusBadRequest, gin.H{"error": "Invalid JSON data: " + err.Error()})
		return
	}

	_, err := db.Exec("UPDATE courses SET course_name = ?, course_time = ?, course_location = ? WHERE id = ?",
		updatedCourse.CourseName, updatedCourse.CourseTime, updatedCourse.CourseLocation, c.Param("id"))
	if err != nil {
		c.JSON(http.StatusInternalServerError, gin.H{"error": "Failed to update course: " + err.Error()})
		return
	}

	c.JSON(http.StatusOK, gin.H{"message": "课程更新成功"})
}

func deleteCourse(c *gin.Context, db *sql.DB) {
	_, err := db.Exec("DELETE FROM courses WHERE id = ?", c.Param("id"))
	if err != nil {
		c.JSON(http.StatusInternalServerError, gin.H{"error": "Failed to delete course: " + err.Error()})
		return
	}

	c.JSON(http.StatusOK, gin.H{"message": "课程删除成功"})
}

func handleOptionsRequest(c *gin.Context) {
	c.Header("Access-Control-Allow-Origin", "*")
	c.Header("Access-Control-Allow-Methods", "GET, POST, PUT, DELETE, OPTIONS")
	c.Header("Access-Control-Allow-Headers", "Content-Type, Authorization")

	// 返回状态码OK表示预检请求成功
	c.JSON(http.StatusOK, gin.H{})

}

func showCreateCourseForm(c *gin.Context) {
	c.HTML(http.StatusOK, "create_course.html", gin.H{})
}

func showUpdateCourseForm(c *gin.Context) {
	courseID := c.Query("id") // 获取查询参数中的课程ID
	c.HTML(http.StatusOK, "update_course.html", gin.H{
		"courseID": courseID,
	})
}

func main() {
	db, err := sql.Open("mysql", "root:123456@tcp(127.0.0.1:3306)/test01")
	if err != nil {
		log.Fatal("Failed to connect to database:", err)
	}
	defer db.Close()

	r := setupRoutes(db)
	r.Run(":8080")
}
